package service

import (
	"buding-ai/internal/core"
	"buding-ai/internal/repository"
	"buding-ai/internal/repository/model"
	"buding-ai/internal/web/dto"
	"buding-ai/internal/web/response"
	"buding-ai/pkg/utils/paginate"
	"buding-ai/pkg/utils/password"
	"errors"
	"fmt"
	"sync"
	"time"
)

var (
	ErrUserExists    = errors.New("user already exists")
	ErrPhoneExists   = errors.New("phone number already exists")
	ErrEmailExists   = errors.New("email already exists")
	ErrDatabaseError = errors.New("a database error occurred")
)

// 用户缓存key前缀
const userCachePrefix = "user:"

// UserService 用户服务
type UserService struct {
	userRepository *repository.UserRepository
}

var (
	userSrv  *UserService
	userOnce sync.Once
)

// NewUserService 创建用户服务实例
func NewUserService() *UserService {
	userOnce.Do(func() {
		userSrv = &UserService{
			userRepository: repository.GeUserRepository(),
		}
	})
	return userSrv
}

// Create 创建用户
func (srv *UserService) Create(userDTO dto.UserCreateDTO) (*model.User, error) {
	// 检查用户名是否已存在
	exists, err := srv.userRepository.CheckUserExistsByUsername(userDTO.Username)
	if err != nil {
		return nil, ErrDatabaseError
	}
	if exists {
		return nil, ErrUserExists
	}

	// 检查手机号是否已存在（如果提供了手机号）
	if userDTO.Phone != "" {
		exists, err := srv.userRepository.CheckPhoneExists(userDTO.Phone)
		if err != nil {
			return nil, ErrDatabaseError
		}
		if exists {
			return nil, ErrPhoneExists
		}
	}

	// 检查邮箱是否已存在（如果提供了邮箱）
	if userDTO.Email != "" {
		exists, err := srv.userRepository.CheckEmailExists(userDTO.Email)
		if err != nil {
			return nil, ErrDatabaseError
		}
		if exists {
			return nil, ErrEmailExists
		}
	}

	// 生成密码和盐值
	encodedPassword, salt := password.GeneratePassword(userDTO.Password)

	// 设置默认值
	if userDTO.Status == 0 {
		userDTO.Status = 1 // 默认启用
	}

	// 创建用户
	user := model.User{
		Username: userDTO.Username,
		Password: encodedPassword,
		Salt:     salt,
		Phone:    userDTO.Phone,
		Email:    userDTO.Email,
		Nickname: userDTO.Nickname,
		Avatar:   userDTO.Avatar,
		Role:     model.UserRole(userDTO.Role),
		Status:   userDTO.Status,
	}

	//
	if err := srv.userRepository.CreateUser(&user); err != nil {
		return nil, ErrDatabaseError
	}

	// 提交事务

	// 返回创建的用户，不返回密码
	user.Password = ""
	user.Salt = ""

	return &user, nil
}

// Delete 删除用户
func (srv *UserService) Delete(id uint64) error {
	// 开启事务
	tx := core.DB.Begin()

	// 检查用户是否存在
	_, err := srv.userRepository.GetByIdUint64(id)
	if err != nil {
		tx.Rollback()
		return ErrUserNotFound
	}

	// 软删除用户
	if err := srv.userRepository.DeleteUser(id); err != nil {
		tx.Rollback()
		return ErrDatabaseError
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return ErrDatabaseError
	}

	// 从缓存删除
	cacheKey := fmt.Sprintf("%s%d", userCachePrefix, id)
	core.AppCache.Delete(cacheKey)

	return nil
}

// Update 更新用户信息
func (srv *UserService) Update(userDTO dto.UserUpdateDTO) error {
	// 开启事务
	tx := core.DB.Begin()

	// 检查用户是否存在
	user, err := srv.userRepository.GetByIdUint64(userDTO.ID)
	if err != nil {
		tx.Rollback()
		return ErrUserNotFound
	}

	// 检查手机号是否被其他用户使用
	if userDTO.Phone != "" && userDTO.Phone != user.Phone {
		exists, err := srv.userRepository.CheckPhoneExistsExcept(userDTO.Phone, userDTO.ID)
		if err != nil {
			tx.Rollback()
			return ErrDatabaseError
		}
		if exists {
			tx.Rollback()
			return ErrPhoneExists
		}
	}

	// 检查邮箱是否被其他用户使用
	if userDTO.Email != "" && userDTO.Email != user.Email {
		exists, err := srv.userRepository.CheckEmailExistsExcept(userDTO.Email, userDTO.ID)
		if err != nil {
			tx.Rollback()
			return ErrDatabaseError
		}
		if exists {
			tx.Rollback()
			return ErrEmailExists
		}
	}

	// 更新用户信息
	updates := map[string]interface{}{
		"nickname":   userDTO.Nickname,
		"phone":      userDTO.Phone,
		"email":      userDTO.Email,
		"avatar":     userDTO.Avatar,
		"role":       userDTO.Role,
		"status":     userDTO.Status,
		"updated_at": time.Now(),
	}

	if err := srv.userRepository.UpdateUser(userDTO.ID, updates); err != nil {
		tx.Rollback()
		return ErrDatabaseError
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return ErrDatabaseError
	}

	// 从缓存删除
	cacheKey := fmt.Sprintf("%s%d", userCachePrefix, userDTO.ID)
	core.AppCache.Delete(cacheKey)

	return nil
}

// GetById 根据ID获取用户信息
func (srv *UserService) GetById(id uint64) (*response.UserVO, error) {
	// 尝试从缓存获取
	cacheKey := fmt.Sprintf("%s%d", userCachePrefix, id)
	if cacheData, found := core.AppCache.Get(cacheKey); found {
		if user, ok := cacheData.(model.User); ok {
			vo := response.ToUserVO(user)
			return &vo, nil
		}
	}

	// 从数据库获取
	user, err := srv.userRepository.GetByIdUint64(id)
	if err != nil {
		return nil, ErrUserNotFound
	}

	// 不返回密码和盐值
	user.Password = ""
	user.Salt = ""

	// 存入缓存
	core.AppCache.Set(cacheKey, *user, 10*time.Minute)

	vo := response.ToUserVO(*user)
	return &vo, nil
}

// GetPage 分页获取用户列表
func (srv *UserService) GetPage(pageRequest paginate.PageRequest) (*paginate.PageResponse, error) {
	// 执行分页查询
	pageResult, err := srv.userRepository.GetUserPage(pageRequest)
	if err != nil {
		return nil, ErrDatabaseError
	}
	return pageResult, nil
}

// ResetPassword 重置用户密码
func (srv *UserService) ResetPassword(id uint64) error {
	// 开启事务
	tx := core.DB.Begin()

	// 检查用户是否存在
	_, err := srv.userRepository.GetByIdUint64(id)
	if err != nil {
		tx.Rollback()
		return ErrUserNotFound
	}

	// 重置密码为123456
	if err := srv.userRepository.ResetPassword(id, "123456"); err != nil {
		tx.Rollback()
		return ErrDatabaseError
	}

	// 提交事务
	if err := tx.Commit().Error; err != nil {
		return ErrDatabaseError
	}

	return nil
}
